package jsu.ljy.lostandfind.dao.impl;

import jsu.ljy.lostandfind.dao.BaseDao;
import jsu.ljy.lostandfind.model.ClaimInfo;
import jsu.ljy.lostandfind.util.DBUtil;
import org.springframework.stereotype.Repository;

import java.sql.*;
import java.util.ArrayList;
import java.util.List;

/**
 * 认领信息数据访问实现类
 * 
 * <p>实现了认领信息相关的数据库操作，包括认领申请的提交、处理、查询等基本操作。
 * 提供了按物品和用户查询认领记录的功能。</p>
 * 
 * @author 罗嘉毅
 * @version 1.0
 * @since 2024-03-21
 */
@Repository
public class ClaimInfoDaoImpl implements BaseDao<ClaimInfo> {

    /**
     * 保存认领信息
     * 
     * @param claimInfo 认领信息
     * @throws RuntimeException 当数据库操作失败时抛出
     */
    @Override
    public void save(ClaimInfo claimInfo) {
        String sql = "INSERT INTO claim_info (item_id, user_id, real_name, student_id, phone, description, create_time, status) VALUES (?, ?, ?, ?, ?, ?, ?, ?)";
        try (Connection conn = DBUtil.getConnection();
             PreparedStatement pstmt = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) {
            pstmt.setLong(1, claimInfo.getItemId());
            pstmt.setLong(2, claimInfo.getUserId());
            pstmt.setString(3, claimInfo.getRealName());
            pstmt.setString(4, claimInfo.getStudentId());
            pstmt.setString(5, claimInfo.getPhone());
            pstmt.setString(6, claimInfo.getDescription());
            pstmt.setTimestamp(7, new Timestamp(claimInfo.getCreateTime().getTime()));
            pstmt.setString(8, claimInfo.getStatus());
            pstmt.executeUpdate();
            
            try (ResultSet rs = pstmt.getGeneratedKeys()) {
                if (rs.next()) {
                    claimInfo.setId(rs.getLong(1));
                }
            }
        } catch (SQLException e) {
            throw new RuntimeException("保存认领信息失败", e);
        }
    }

    /**
     * 更新认领信息
     * 
     * @param claimInfo 认领信息
     * @throws RuntimeException 当数据库操作失败时抛出
     */
    @Override
    public void update(ClaimInfo claimInfo) {
        String sql = "UPDATE claim_info SET status = ? WHERE id = ?";
        try (Connection conn = DBUtil.getConnection();
             PreparedStatement pstmt = conn.prepareStatement(sql)) {
            pstmt.setString(1, claimInfo.getStatus());
            pstmt.setLong(2, claimInfo.getId());
            pstmt.executeUpdate();
        } catch (SQLException e) {
            throw new RuntimeException("更新认领信息失败", e);
        }
    }

    /**
     * 删除认领信息
     * 
     * @param id 认领信息ID
     * @throws RuntimeException 当数据库操作失败时抛出
     */
    @Override
    public void delete(Long id) {
        String sql = "DELETE FROM claim_info WHERE id = ?";
        try (Connection conn = DBUtil.getConnection();
             PreparedStatement pstmt = conn.prepareStatement(sql)) {
            pstmt.setLong(1, id);
            pstmt.executeUpdate();
        } catch (SQLException e) {
            throw new RuntimeException("删除认领信息失败", e);
        }
    }

    /**
     * 根据ID查询认领信息
     * 
     * @param id 认领信息ID
     * @return 认领信息，不存在时返回null
     * @throws RuntimeException 当数据库操作失败时抛出
     */
    @Override
    public ClaimInfo findById(Long id) {
        String sql = "SELECT * FROM claim_info WHERE id = ?";
        try (Connection conn = DBUtil.getConnection();
             PreparedStatement pstmt = conn.prepareStatement(sql)) {
            pstmt.setLong(1, id);
            try (ResultSet rs = pstmt.executeQuery()) {
                if (rs.next()) {
                    return mapResultSetToClaimInfo(rs);
                }
            }
        } catch (SQLException e) {
            throw new RuntimeException("查询认领信息失败", e);
        }
        return null;
    }

    /**
     * 查询所有认领信息
     * 
     * @return 认领信息列表，按创建时间降序排序
     * @throws RuntimeException 当数据库操作失败时抛出
     */
    @Override
    public List<ClaimInfo> findAll() {
        String sql = "SELECT * FROM claim_info ORDER BY create_time DESC";
        List<ClaimInfo> claims = new ArrayList<>();
        try (Connection conn = DBUtil.getConnection();
             PreparedStatement pstmt = conn.prepareStatement(sql);
             ResultSet rs = pstmt.executeQuery()) {
            while (rs.next()) {
                claims.add(mapResultSetToClaimInfo(rs));
            }
        } catch (SQLException e) {
            throw new RuntimeException("查询所有认领信息失败", e);
        }
        return claims;
    }

    /**
     * 根据物品ID查询认领信息列表
     * 
     * @param itemId 物品ID
     * @return 认领信息列表，按创建时间降序排序
     * @throws RuntimeException 当数据库操作失败时抛出
     */
    public List<ClaimInfo> findByItemId(Long itemId) {
        String sql = "SELECT * FROM claim_info WHERE item_id = ? ORDER BY create_time DESC";
        List<ClaimInfo> claims = new ArrayList<>();
        try (Connection conn = DBUtil.getConnection();
             PreparedStatement pstmt = conn.prepareStatement(sql)) {
            pstmt.setLong(1, itemId);
            try (ResultSet rs = pstmt.executeQuery()) {
                while (rs.next()) {
                    claims.add(mapResultSetToClaimInfo(rs));
                }
            }
        } catch (SQLException e) {
            throw new RuntimeException("查询物品认领信息失败", e);
        }
        return claims;
    }

    /**
     * 根据用户ID查询认领信息列表
     * 
     * @param userId 用户ID
     * @return 认领信息列表，按创建时间降序排序
     * @throws RuntimeException 当数据库操作失败时抛出
     */
    public List<ClaimInfo> findByUserId(Long userId) {
        String sql = "SELECT * FROM claim_info WHERE user_id = ? ORDER BY create_time DESC";
        List<ClaimInfo> claims = new ArrayList<>();
        try (Connection conn = DBUtil.getConnection();
             PreparedStatement pstmt = conn.prepareStatement(sql)) {
            pstmt.setLong(1, userId);
            try (ResultSet rs = pstmt.executeQuery()) {
                while (rs.next()) {
                    claims.add(mapResultSetToClaimInfo(rs));
                }
            }
        } catch (SQLException e) {
            throw new RuntimeException("查询用户认领信息失败", e);
        }
        return claims;
    }

    /**
     * 将ResultSet映射为ClaimInfo对象
     * 
     * @param rs 结果集
     * @return ClaimInfo对象
     * @throws SQLException 当数据库操作失败时抛出
     */
    private ClaimInfo mapResultSetToClaimInfo(ResultSet rs) throws SQLException {
        ClaimInfo claimInfo = new ClaimInfo();
        claimInfo.setId(rs.getLong("id"));
        claimInfo.setItemId(rs.getLong("item_id"));
        claimInfo.setUserId(rs.getLong("user_id"));
        claimInfo.setRealName(rs.getString("real_name"));
        claimInfo.setStudentId(rs.getString("student_id"));
        claimInfo.setPhone(rs.getString("phone"));
        claimInfo.setDescription(rs.getString("description"));
        claimInfo.setCreateTime(rs.getTimestamp("create_time"));
        claimInfo.setStatus(rs.getString("status"));
        return claimInfo;
    }
} 